package ua.lviv.franko.solvers.stressanalysis.oneDimention.cylindrical;

import java.util.List;

import ua.lviv.franko.integration.GaussQuadrature;
import ua.lviv.franko.integration.IFunction1D;
import ua.lviv.franko.integration.Quadrature;

public abstract class AbstractElement1D {
	
	public static int NUMBER_OF_UNKNOWNS = 2;

	public static int				QuadraturePointsNumber	= 19;
	protected Quadrature			gau;
	// problem data
	protected EquationParameters	eParams;
	// element number starting from 0
	protected int					elNumber;
	// element information
	protected final double			left;
	protected final double			right;
	protected List<IFunction1D>		baseFunctions;

	// results
	protected ElementMatrix			data;

	public AbstractElement1D(final EquationParameters eParams, int elNumber, final double left, final double right) {
		super();
		gau = new GaussQuadrature(QuadraturePointsNumber);
		this.eParams = eParams;
		this.elNumber = elNumber;
		this.left = left;
		this.right = right;
		this.eParams = eParams;
	}

	public abstract double[] calculate(double x, double[] results);
	public abstract double[] calculateDerivaty(double x, double[] results);

	public ElementMatrix generateAll() {
		ElementMatrix data = new ElementMatrix(this.getNodesNumbers());
		int N = baseFunctions.size();
		for (int i = 0; i < N; i++) {
			ElementMatrix tmp = this.calculateSmallData(i, i);

			data.vector[NUMBER_OF_UNKNOWNS * i] = tmp.vector[0];
			data.vector[NUMBER_OF_UNKNOWNS * i + 1] = tmp.vector[1];

			for (int j = 0; j < N; j++) {
				tmp = this.calculateSmallData(i, j);

				data.matrix[i * NUMBER_OF_UNKNOWNS][j * NUMBER_OF_UNKNOWNS] = tmp.matrix[0][0];
				data.matrix[i * NUMBER_OF_UNKNOWNS][j * NUMBER_OF_UNKNOWNS + 1] = tmp.matrix[0][1];

				data.matrix[i * NUMBER_OF_UNKNOWNS + 1][j * NUMBER_OF_UNKNOWNS] = tmp.matrix[1][0];
				data.matrix[i * NUMBER_OF_UNKNOWNS + 1][j * NUMBER_OF_UNKNOWNS + 1] = tmp.matrix[1][1];

			}

		}

		return data;
	}
	
	public ElementMatrix generateUpdatedVector(EquationParameters parameters){
		ElementMatrix data = new ElementMatrix(this.getNodesNumbers());
		int N = baseFunctions.size();
		for (int i = 0; i < N; i++) {
			double[] tmp = this.calculateSmallUpdatedVector(i, parameters);

			data.vector[NUMBER_OF_UNKNOWNS * i] = tmp[0];
			data.vector[NUMBER_OF_UNKNOWNS * i + 1] = tmp[1];
		}

		return data;
	};
	
	protected abstract double[] calculateSmallUpdatedVector(int i,EquationParameters parameters);

	protected abstract ElementMatrix calculateSmallData(int i, int j);

	public abstract List<Integer> getNodesNumbers();

	public List<IFunction1D> getBaseFunctions() {
		return baseFunctions;
	}

	public double getLeft() {
		return left;
	}

	public double getRight() {
		return right;
	}
	
	public EquationParameters getEquationParameters() {
		return eParams;
	}

}
